From 4c8688811f74e58a04bf5f10e0240e7c0c11b510 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 12 Jan 2007 10:08:38 +0000 Subject: [PATCH] [HVM] Fix timer interrupt delivery on x64 Vista. x64 SMP Vista HVM guest uses HPET as the main system timer, and it uses physical destination mode with broadcast to deliver the interrupts generated by HPET. In current code, timer interrupts are injected only to VCPU0 in vioapic.c, but this doesn't satisfy x64 SMP Vista -- when it boots, it complains "a clock interrupt was not received on a secondary processor within the allocated time interval" with Bug Check 0x101. Signed-off-by: Dexuan Cui --- xen/arch/x86/domain.c | 2 +- xen/arch/x86/hvm/vioapic.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b03824f5ca..e23c85bbaa 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1047,7 +1047,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next) local_irq_disable(); - if ( is_hvm_vcpu(prev) ) + if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) ) pt_freeze_time(prev); set_current(next); diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 843c76a6dd..6f68a85b77 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -309,6 +309,13 @@ static uint32_t ioapic_get_delivery_bitmask( return mask; } +static inline int pit_channel0_enabled(void) +{ + PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit; + struct periodic_time *pt = &pit->channels[0].pt; + return pt->enabled; +} + static void vioapic_deliver(struct vioapic *vioapic, int irq) { uint16_t dest = vioapic->redirtbl[irq].fields.dest_id; @@ -341,7 +348,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq) { #ifdef IRQ0_SPECIAL_ROUTING /* Force round-robin to pick VCPU 0 */ - if ( irq == hvm_isa_irq_to_gsi(0) ) + if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() ) { v = vioapic_domain(vioapic)->vcpu[0]; target = v ? vcpu_vlapic(v) : NULL; @@ -374,7 +381,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq) deliver_bitmask &= ~(1 << bit); #ifdef IRQ0_SPECIAL_ROUTING /* Do not deliver timer interrupts to VCPU != 0 */ - if ( irq == hvm_isa_irq_to_gsi(0) ) + if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() ) v = vioapic_domain(vioapic)->vcpu[0]; else #endif -- 2.30.2